﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Pibby.Core.Presenters;

namespace Pibby.Core.Tests
{
	public class StartingObject
	{
		public int Value
		{
			get;
			set;
		}
	}

	public class ProgressValue
	{
		public int Value
		{
			get;
			set;
		}
	}

	[TestClass]
	public class BackgroundProcessingTests
	{
		private BackgroundProcessing _worker;

		[TestMethod]
		public void SimpleOperationNoProgressCompletes()
		{
			StartingObject startingObject = new StartingObject();
			startingObject.Value = 42;
		
			this._worker = BackgroundProcessing.Create<StartingObject>(SimpleOperationNoProgressThreadedMethod,
				SimpleOperationNoProgressCompletionMethod,
				SimpleOperationNoProgressExceptionHandler,
				startingObject);
			
			this._worker.Run();
		}


		public static void SimpleOperationNoProgressThreadedMethod(BackgroundWorker worker, StartingObject obj)
		{
			// what do we do here ????
			Assert.IsNotNull(worker);
			Assert.AreEqual(42, obj.Value);
		}

		public void SimpleOperationNoProgressCompletionMethod()
		{
			if (this._worker != null)
			{
				this._worker.Dispose();
				this._worker = null;
			}
		}

		public void SimpleOperationNoProgressExceptionHandler(Exception ex)
		{
			Assert.Fail("Should not get an exception in this test");
		}

		[TestMethod]
		public void SimpleOperationThrowsExceptionInThread()
		{
			StartingObject startingObject = new StartingObject();
			startingObject.Value = 666;

			this._worker = BackgroundProcessing.Create<StartingObject>(SimpleOperationThrowsExceptionThreadedMethod,
				SimpleOperationThrowsExceptionCompletionMethod,
				SimpleOperationThrowsExceptionExceptionHandler,
				startingObject);

			this._worker.Run();
		}


		public static void SimpleOperationThrowsExceptionThreadedMethod(BackgroundWorker worker, StartingObject obj)
		{
			// what do we do here ????
			Assert.IsNotNull(worker);
			Assert.AreEqual(666, obj.Value);

			throw new ArgumentException("Object is not initialised correctly", "obj");
		}

		public void SimpleOperationThrowsExceptionCompletionMethod()
		{
			Assert.Fail("Should get an exception in this test");
		}

		public void SimpleOperationThrowsExceptionExceptionHandler(Exception ex)
		{
			Assert.IsNotNull(ex);
			Assert.IsNotNull(ex.InnerException);

			ArgumentException argEx = ex.InnerException as ArgumentException;

			Assert.IsNotNull(argEx);
			Assert.AreEqual("obj", argEx.ParamName);

		}


		[TestMethod]
		public void ProgressOperationCompletes()
		{
			StartingObject startingObject = new StartingObject();
			startingObject.Value = 999;

			this._worker = BackgroundProcessing.Create<StartingObject, ProgressValue>(ProgressOperationThreadedMethod,
				ProgressOperationProgressMethod, 
				ProgressOperationCompletionMethod,
				ProgressOperationExceptionHandler,
				startingObject);

			this._worker.Run();
		}


		public static void ProgressOperationThreadedMethod(BackgroundWorker worker, StartingObject obj)
		{
			Assert.IsNotNull(worker);
			Assert.AreEqual(999, obj.Value);

			for (int i = 0; i < 100; ++i)
			{
				int k = (i * 100) * (i + 10);

				++k;

				worker.ReportProgress(i, new ProgressValue() { Value = i });
			}
		}

		public void ProgressOperationProgressMethod(ProgressValue value)
		{
			//Assert.Greater(value.Value, -1);
			//Assert.Less (value.Value, 101);
		}

		public void ProgressOperationCompletionMethod()
		{
			if (this._worker != null)
			{
				this._worker.Dispose();
				this._worker = null;
			}
		}

		public void ProgressOperationExceptionHandler(Exception ex)
		{
			Assert.Fail("Should not get here");
		}

	}
}
